﻿using ServiceStack.Web;
using System;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using Ymatou.Counter.Client40;
using Ymatou.User.Dto.Auth;
using YmtAuth.AppService.JavaService;
using YmtAuth.Domain.EventHistory;
using YmtAuth.Domain.Model.LoginAuth;
using YmtAuth.Domain.Model.Safe;
using YmtAuth.Domain.Model.YmatouUser.Event;
using YmtAuth.Domain.Repository;
using YmtAuth.Domain.Repository.EventRepository;
using YmtAuth.Dto;
using YmtAuth.LogService;
using YmtSystem.CrossCutting;

namespace YmtAuth.AppService
{
    public class AuthQueryAppService : IAuthQueryAppService
    {
        private ILoginIdUpdateEventRepository LoginIdUpdateEventRepo { get { return LocalServiceLocator.GetService<ILoginIdUpdateEventRepository>(); } }
        private IUserLoginBillsRepository UlBRepository { get { return LocalServiceLocator.GetService<IUserLoginBillsRepository>(); } }
        private IYmtUserLoginHistoryRepository LoginHistoryRepo { get { return LocalServiceLocator.GetService<IYmtUserLoginHistoryRepository>(); } }

        public ResponseData<BillsExistsResponseDto> FindLoginBillsExists(UserBillsExistsRequestDto dto, IRequest request = null)
        {

            if (request != null)
            {
                if (RequestUserService.isSendReadToJavaUserService(dto, "UserBillsExistsRequestDto", "GET", new string[] { dto.UserId.ToString() }))
                {
                    var result = RequestUserService.sendReadRequest<ResponseData<BillsExistsResponseDto>>(dto, "UserBillsExistsRequestDto", request.RawUrl, "GET",
                        request.QueryString);
                    if (result.isRequestSuccess) return result.resp;
                }
            }

            var exists = new BillsExistsResponseDto();
            if (!string.IsNullOrEmpty(dto.LoginId))
            {
                if (dto.UserId > 0)
                {
                    if (UlBRepository.Exists(UserLoginAuthSpecifications.NotMatchLoginIdByUserId(dto.LoginId, dto.UserId)))
                        exists.LoginIdExists = true;
                }
                else
                {
                    var user = UlBRepository.FindOne(UserLoginAuthSpecifications.MatchLoginId(dto.LoginId), true);
                    if (user != null)
                    {
                        //如果第三方用户，则记录日志
                        WriteLog(dto, user.UserId);
                        exists.LoginIdExists = true;
                    }
                    else
                    {
                        WriteLog(dto, 0);
                    }
                }
            }
            if (!string.IsNullOrEmpty(dto.Mobile))
            {
                if (dto.UserId > 0)
                {
                    if (UlBRepository.Exists(UserLoginAuthSpecifications.NotMatchLoginMobileByUserId(dto.Mobile, dto.UserId)))
                        exists.MobileExists = true;
                }
                else
                {
                    if (UlBRepository.Exists(UserLoginAuthSpecifications.MatchLoginMobile(dto.Mobile)))
                        exists.MobileExists = true;
                }
            }
            if (!string.IsNullOrEmpty(dto.EMail))
            {
                if (dto.UserId > 0)
                {
                    if (UlBRepository.Exists(UserLoginAuthSpecifications.NotMatchLoginMailByUserId(dto.EMail, dto.UserId)))
                        exists.EMailExists = true;
                }
                else
                {
                    if (UlBRepository.Exists(UserLoginAuthSpecifications.MatchLoginMail(dto.EMail)))
                        exists.EMailExists = true;
                }
            }
            return ResponseData<BillsExistsResponseDto>.CreateSuccess(exists, "ok");
        }



        public ResponseData<long> GetModifyLoginIdCount(BillsLoginIdModifyEventRequestDto dto, IRequest request=null)
        {
            if (request != null)
            {
                if (RequestUserService.isSendReadToJavaUserService(dto, "BillsLoginIdModifyEventRequestDto", "GET", new string[] { dto.LoginId, dto.UserId.ToString()}))
                {
                    var result = RequestUserService.sendReadRequest<ResponseData<long>>(dto, "BillsLoginIdModifyEventRequestDto", request.RawUrl, "GET",
                        request.QueryString);
                    if (result.isRequestSuccess) return result.resp;
                }
            }

            long count = 0;
            if (dto.UserId > 0)
                count = GetModifyLoginIdCount(dto.UserId, dto.ActionSource);
            else if (!string.IsNullOrEmpty(dto.LoginId))
                count = GetModifyLoginIdCount(dto.LoginId, dto.ActionSource);

            return ResponseData<long>.CreateSuccess(count, "ok");
        }

        /// <summary>
        /// 获取登录失败的次数
        /// </summary>    
        public int GetLoginFailCount(LoginLimitRequestDto dto, IRequest request = null)
        {
            if (request != null)
            {
                if (RequestUserService.isSendReadToJavaUserService(dto, "LoginLimitRequestDto", "GET", new string[] { dto.LoginId}))
                {
                    var result = RequestUserService.sendReadRequest<int>(dto, "LoginLimitRequestDto", request.RawUrl, "GET",
                        request.QueryString);
                    if (result.isRequestSuccess) return result.resp;
                }
            }

            YmtSystemAssert.AssertArgumentNotNull(dto, "无效的LoginLimitRequestDto");
            YmtSystemAssert.AssertArgumentNotEmpty(dto.LoginId, "无效的LoginId");
            var ts = dto.TimeSpan > 0 ? -dto.TimeSpan : dto.TimeSpan;
            //如果禁用请求计数器服务，则直接从mongodb统计数据
            //if (ConfigurationManager.AppSettings["CounterService_R_LoginCount"].IsEmpty()
            //    || ConfigurationManager.AppSettings["CounterService_R_LoginCount"] == "0")
            //    return
            //        (int)
            //            LoginHistoryRepo.Count(
            //                LoginEventSpecifications.MatchLoginFailLimitMongoQuery(dto.LoginId, TimeSpan.FromMinutes(ts)),
            //                LoginEventSpecifications.LoginLogDb, LoginEventSpecifications.LoginLogTb());
            //请求计算器服务
            var count = LoginHistoryRepo.GetUserLoginCount(LoginEventSpecifications.AUTHSERVICE_KEY,
                LoginEventSpecifications.GenerateLoginSpecKey(dto.LoginId, AuthSafeHandleCode.LoginPasswordError)
                , DateTime.Now.AddMinutes(ts), DateTime.Now);
            if (count > -1)
                return count;
            //如果计数器服务异常则执行mongodb数据计算
            return
                (int)
                    LoginHistoryRepo.Count(
                        LoginEventSpecifications.MatchLoginFailLimitMongoQuery(dto.LoginId, TimeSpan.FromMinutes(ts)),
                        LoginEventSpecifications.LoginLogDb, LoginEventSpecifications.LoginLogTb());
        }

        private void WriteLog(UserBillsExistsRequestDto dto, int userId = 0)
        {
            if (!string.IsNullOrEmpty(dto.CSource) &&
                (dto.CSource.ToLower() != "mainsite" && dto.CSource.ToLower() != "wap" && dto.CSource.ToLower() != "app"))
            {
                LogTask.Instance.EnQueue(new ThirdPartyUserLoginLog
                {
                    sLoginId = dto.LoginId,
                    iAction = userId,
                    sLoginIp = dto.ClientIp,
                    CSource = dto.CSource,
                    TSource = dto.TSource,
                });
            }
        }

        private long GetModifyLoginIdCount(int userId, UserSource actionSource)
        {
            return LoginIdUpdateEventRepo.Count(EventSpecifications.MatchUserLoginIdUpdate(userId, actionSource));
        }
        private long GetModifyLoginIdCount(string mobile, UserSource actionSource)
        {
            return LoginIdUpdateEventRepo.Count(EventSpecifications.MatchUserLoginIdUpdate(mobile, actionSource));
        }
    }
}
